#include "ilog.h"

const char LEVEL_I2A[5][10] = { "BEBUG", "WARN", "INFO", "ERROR", "FATAL"};

static void baselog(char *filename, ulong fileline, char *format, ...)
{
	va_list ap;
	va_start(ap, format);
	fprintf(stderr, "[logselferr] file:%s line:%lu msg:", filename, fileline);
	vfprintf(stderr, format, ap);
	fprintf(stderr, "\n");
	va_end(ap);
}	
int AppendMsgToBuf(char **bufcurptr, ulong *usedlen, ulong *remainlen, char *format, ...) 
{
	if (bufcurptr == NULL || *bufcurptr == NULL )
		return -1;
	va_list ap;
	va_start(ap, format);
	if (*remainlen > 0) { 
		int __len__ = vsnprintf(*bufcurptr, *remainlen, format, ap); 
		*bufcurptr += __len__; 
		*usedlen += __len__; 
		*remainlen -= __len__; 
		va_end(ap);
		return __len__;
	}
	else {
		va_end(ap);	
		return 0;
	}
}


TLS char glogpathfilename[LOGFILEMAXLEN + 1];
TLS int gloglevel;

int SetLogFile( char *format, ...) 
{
	if (format == NULL) {
		return -1;
	}
	va_list ap;
	va_start(ap, format);
	vsnprintf( glogpathfilename, sizeof(glogpathfilename) - 1, format, ap );
	va_end( ap );

	return 0;
}
int SetLogLevel( int l )
{
	if (l >= sizeof(LEVEL_I2A) / sizeof(LEVEL_I2A[0]) )
	{
		return -1;
	}
	gloglevel = l;
}
char* GenerateMsg(char *outbuf, ulong *outbuflen, int loglevel, char *c_filename, ulong c_fileline, char *format, va_list valist)
{
	char *logbuf = NULL;
	int r = 0;
	/* 路径+文件名 */
	char *p_c_filenamestart = NULL;
	char c_filename_copy[LOGFILEMAXLEN + 1];
	int c_filenamelen;
	struct timeval tv;
	struct tm time;
	char *poutbufpos = NULL;
	ulong usedlen = 0, remainlen = 0;
	ulong len = 0;

	if (outbuf == NULL) {
		logbuf = malloc( LOGBUFLEN + 1 ); 
		if (logbuf == NULL)
			return NULL;
		memset(logbuf, 0x00, LOGBUFLEN + 1);
		outbuf = logbuf;
		remainlen = LOGBUFLEN;
	}
	else {
		if (outbuflen == NULL)
			return NULL;
		remainlen = *outbuflen;
	}
		
	usedlen = 0;
	poutbufpos = outbuf;

	memset(c_filename_copy, 0x00, sizeof(c_filename_copy));
	strcpy(c_filename_copy, c_filename);
	p_c_filenamestart = strchr(c_filename_copy, '/'); 
	if (p_c_filenamestart == NULL) 
		p_c_filenamestart = c_filename_copy;
	else 
		p_c_filenamestart++;

	gettimeofday(&tv, NULL);
	localtime_r(&(tv.tv_sec), &time);

	memset(outbuf, 0x00, sizeof(outbuf));
	char temp[1024];
	memset(temp, 0x00, sizeof(temp));
	len = strftime( temp, sizeof(temp) - 1 , "%Y-%m-%d %H:%M:%S" , &time ) ;

	AppendMsgToBuf(&poutbufpos, &usedlen, &remainlen, "%s", temp);
//	AppendMsgToBuf(outbuf, poutbufpos, ".%06ld" , (long)(tv.tv_usec) ) ;
	AppendMsgToBuf(&poutbufpos, &usedlen, &remainlen, "|%-5s" , LEVEL_I2A[loglevel] ) ;

#if (defined _THREADLOG_) 
	AppendMsgToBuf(&poutbufpos, &usedlen, &remainlen, "|%lu:%lu:%s:%lu|", PROCESSID , THREADID , p_c_filenamestart , c_fileline ) ;
#else
	AppendMsgToBuf(&poutbufpos, &usedlen, &remainlen, "|%lu:%s:%lu|", PROCESSID , p_c_filenamestart , c_fileline ) ;
#endif

	len = vsnprintf(poutbufpos, remainlen, format, valist);
	usedlen += len;
	poutbufpos += len;
	remainlen -= len;
	ADDNEWLINE(poutbufpos, usedlen, remainlen);

	if (outbuflen != NULL)
		*outbuflen = usedlen; 

	return outbuf;
}

int WriteBase( char *msg, int msglen )
{
	if (strcmp( glogpathfilename, "STDOUT" ) == 0 ) {
		write( 1, msg, msglen);	
	}
	else if (strcmp( glogpathfilename, "STDERR" ) == 0 ) {
		write( 2, msg, msglen);	
	}
	else if ( glogpathfilename[0] ) {
		//普通文件
		int fd = open( glogpathfilename, O_CREAT | O_WRONLY | O_APPEND , S_IRWXU | S_IRWXG | S_IRWXO ) ;
		if (fd < 0) {
			return -1;
		}
		write( fd, msg, msglen );
		close(fd);
	}
	return 0;
}
int ErrorLog(char *c_filename, ulong c_fileline, char *format, ...)
{
	va_list ap;
	char *p = NULL;	
	ulong len = 0;
	int r = 0;
	if ( LOG_LEVEL_ERROR < gloglevel ) {
		return 0;
	}

	va_start( ap, format );
	p = GenerateMsg(NULL, NULL, LOG_LEVEL_ERROR, c_filename, c_fileline, format, ap );
	if (p == NULL) {
		r = -1;
		goto E;
	}
	len = strlen( p );	
	if (!len){
		r = 0;
		goto E;
	}
	r = WriteBase( p, len );
	if (r) {
		goto E;
	}
E:
	va_end( ap );
	free(p);
	p = NULL;

	return r;
}
